#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author      : moshan
# Mail        : mo_shan@yeah.net
# Version     : 1.0
# Created Time: 2021-02-21 10:40:02
# Function    : 主程序
#########################################################################
import sys, time, threading, json, random
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.client import ServerProxy
from optparse import OptionParser

from lib.Config import *
from lib.ConnectMySQL import *
from lib.Public import *
from lib.MonitorSQL import *

def f_alertwrite_to_mysql(DB,data, info, title, n_time = 5) :

    sql = "select rshost from tb_monitor_alert_info where istate > 0 and (n_time > now() or a_time > date_add(now(), INTERVAL - 2 MINUTE));"

    status, res, DB = f_query_mysql(DB, "select", {"sql" : sql})

    alert_list = []

    if res is None or len(res) == 0 :

        pass

    else :

        for node in res : alert_list.append(node[0])

    replace_sql = {}
 
    error_members = []
    if data is None or len(data) == 0:

        pass

    else :

        for node in data :

            if title == "机器告警" :

                alert_name = node[0].split(":::")[0]
                alert_info = title + "-" + node[0].split(":::")[1]

            else :

                alert_name = node[0].split(":::")[0]
                alert_info = info

            if title == "告警恢复" :

                replace_sql[node[0]] = """update """ + t_alert_info + """ set istate = 0 where rshost = '""" + alert_name + """';"""
                error_members.append(alert_name)

                continue

            if alert_name in alert_list :

                replace_sql[node[0]] = """insert into """ + t_alert_info + """(rshost,istate,a_time,remarks) 
                    values('""" + alert_name + """', 1,DATE_FORMAT( DATE_SUB(now(), INTERVAL -0 MINUTE), '%Y-%m-%d %H:%i:00'),'""" + alert_info + """') 
                    on duplicate key update istate=1,a_time = DATE_FORMAT( DATE_SUB(now(), INTERVAL -0 MINUTE), '%Y-%m-%d %H:%i:00');"""

            else :

                replace_sql[node[0]] = """insert into """ + t_alert_info + """(rshost,istate,a_time,n_time,remarks) 
                    values('""" + alert_name + """', 1,DATE_FORMAT( DATE_SUB(now(), INTERVAL -0 MINUTE), '%Y-%m-%d %H:%i:00'),DATE_FORMAT( DATE_SUB(now(), INTERVAL -""" + str(n_time) + """ MINUTE), '%Y-%m-%d %H:%i:00'),'""" + alert_info + """') 
                    on duplicate key update istate=istate + 1,a_time = DATE_FORMAT( DATE_SUB(now(), INTERVAL -0 MINUTE), '%Y-%m-%d %H:%i:00'),n_time = DATE_FORMAT( DATE_SUB(now(), INTERVAL -""" + str(n_time) + """ MINUTE), '%Y-%m-%d %H:%i:00');"""

                error_members.append(alert_name + ":" + alert_info)

        status, data, DB = f_query_mysql(DB, "insert", replace_sql)
        if (status != 0) :

            f_write_log(log_opt = "ERROR", log = "[ 告警状态更新失败 ] [ " + "n".join(replace_sql.values()) + " ] ", log_file = log_file)

        if len(error_members) > 0 : 

            f_write_log(log_opt = "ERROR", log = "[ " + title + "的节点有 : " + ",".join(error_members) + " ]", log_file = log_file)

    if len(error_members) == 0 : res = {}

    else : res = {title : error_members}

    return DB, res

def f_manager_node_status(DB, options) :

    remove_members = []

    sql = "select rshost,istate from " + t_host_config + " where istate in (0,1);"

    status, data, DB = f_query_mysql(DB, "select", {"sql" : sql})

    update_sql = {}

    if data is None or len(data) == 0:

        pass

    else :

        for node in data :

            remove_members.append(node)

            update_sql[node[0]] = "update " + t_host_config + " set istate = (if(istate = 1, 2 , if(istate = 2, 2 , -1))) where rshost = '" + node[0] + "'"

        if len(update_sql) > 0 :

            status, data, DB = f_query_mysql(DB, "insert", update_sql)

            if (status != 0) :

                f_write_log(log_opt = "ERROR", log = "[ 节点状态更新失败 ] [ " + "n".join(update_sql.values()) + " ] ", log_file = log_file)

    mark, res = f_manager_state_for_node(remove_members, script_dir, log_file, options.server_host, options.rpc_port)

    if mark != 0 :

        f_send_alert_to_bot("进程监控, 节点管理异常 : " + ",".join(res.keys()))

    return DB

def f_monitor_node_status(DB) :

    #检查监控状态, 如果有超过两分钟没有上报状态的节点就告警
    sql = """select rshost,remarks from """ + t_host_config + """ where istate = 2 and rshost not in (select rshost from """ + t_host_info + """
        where a_time > date_add(now(), INTERVAL - 2 MINUTE) group by rshost)
        and rshost not in (select rshost from """ + t_alert_info + """ where (istate > 0 and a_time > date_add(now(), INTERVAL - 10 MINUTE)) or istate >= 10);"""

    status, data, DB = f_query_mysql(DB, "select", {"sql" : sql})

    error_members = []

    replace_sql = {}

    if data is None or len(data) == 0:

        pass

    else :

        for node in data :

            replace_sql[node[0]] = """insert into """ + t_alert_info + """(rshost,istate,a_time,remarks) 
                values('""" + node[0] + """', 1,now(),'超过2min未上报') 
                on duplicate key update istate=istate +1,a_time=now();"""

            error_members.append(node[0] + ":" + node[1])

        status, data, DB = f_query_mysql(DB, "insert", replace_sql)

        if (status != 0) :

            f_write_log(log_opt = "ERROR", log = "[ 告警状态更新失败 ] [ " + "n".join(replace_sql.values()) + " ] ", log_file = log_file)

        f_write_log(log_opt = "ERROR", log = "[ 超过2min未上报的节点有 : " + ",".join(error_members) + " ]", log_file = log_file)

        f_send_alert_to_bot("进程监控, 超过2min未上报的节点有 : " + ",".join(error_members))

    return DB

def f_monitor_alert_ok(DB) :

    #检查监控状态, 恢复的告警提示
    sql = """select concat(rshost,':::',remarks) from """ + t_alert_info + """ where istate > 0 and a_time < DATE_FORMAT( DATE_SUB(now(), INTERVAL +2 MINUTE), '%Y-%m-%d %H:%i:00');"""

    status, data, DB = f_query_mysql(DB, "select", {"sql" : sql})

    replace_sql = {}

    error_members = {}

    if data is None or len(data) == 0:

        pass

    else :

        info = ""
        title = "告警恢复"
        DB,error_members = f_alertwrite_to_mysql(DB, data, info, title)

    return DB,error_members

def f_delete_monitor_data(DB) :
    #检查监控数据, 保留retention_day天数
    delete_sql = {}

    for t in monitor_table_list :

        delete_sql[t] = "delete from " + t + " where a_time < date_add(now(), INTERVAL - " + d_retention + " DAY) limit 10000;"

    status, data, DB = f_query_mysql(DB, "insert", delete_sql)

    if (status != 0) :

        f_write_log(log_opt = "ERROR", log = "[ 历史监控数据清理失败 ] [ " + "n".join(delete_sql.values()) + " ] ", log_file = log_file)

    return DB

def f_monitor_data_dir(DB, m_size, m_type) :

    sql = f_get_monitor_data_dir_sql(str(m_size), m_type)

    status, data, DB = f_query_mysql(DB, "select", {"sql" : sql})

    replace_sql = {}
 
    error_members = {}

    if data is None or len(data) == 0:

        pass

    else :

        info = """数据目录告警-连续三""" + m_type + """,""" + m_type + """增长量超过""" + m_size + """GB"""
        title = "数据目录告警"
        DB,error_members = f_alertwrite_to_mysql(DB,data, info, title,60)

    return DB, error_members

def f_monitor_host(DB, rule) :

    sql = f_get_monitor_host_sql(rule)

    status, data, DB = f_query_mysql(DB, "select", {"sql" : sql})
 
    error_members = {}

    if data is None or len(data) == 0:

        pass

    else :

        info = """机器告警"""
        title = info
        DB,error_members = f_alertwrite_to_mysql(DB,data, info, title)

    return DB, error_members
